package cn.aicnn.chatssespringboot.service.test;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.util.*;

public class JavaCodeMetricsAnalyzer {

    // 度量结果存储
    private static class MetricResults {
        // 功能点度量
        int externalInputs = 0;
        int externalOutputs = 0;
        int externalQueries = 0;
        int internalLogicalFiles = 0;
        int externalInterfaceFiles = 0;

        // CK度量
        int wmc = 0; // 类的加权方法数
        int dit = 0; // 继承树深度
        int noc = 0; // 子类数
        int cbo = 0; // 类间耦合度
        int rfc = 0; // 类的响应集合
        int lcom = 0; // 方法内聚缺乏度

        // LK度量
        int cyclomaticComplexity = 0;
        int linesOfCode = 0;
        int commentLines = 0;
        double commentDensity = 0.0;

        // 用例图度量
        int useCasePoints = 0;
        int actors = 0;
        int useCases = 0;

        @Override
        public String toString() {
            return "=== 功能点度量 ===\n" +
                    "外部输入数(EI): " + externalInputs + "\n" +
                    "外部输出数(EO): " + externalOutputs + "\n" +
                    "外部查询数(EQ): " + externalQueries + "\n" +
                    "内部逻辑文件(ILF): " + internalLogicalFiles + "\n" +
                    "外部接口文件(EIF): " + externalInterfaceFiles + "\n\n" +

                    "=== CK度量 ===\n" +
                    "加权方法数(WMC): " + wmc + "\n" +
                    "继承树深度(DIT): " + dit + "\n" +
                    "子类数(NOC): " + noc + "\n" +
                    "类间耦合度(CBO): " + cbo + "\n" +
                    "类的响应集合(RFC): " + rfc + "\n" +
                    "方法内聚缺乏度(LCOM): " + lcom + "\n\n" +

                    "=== LK度量 ===\n" +
                    "圈复杂度: " + cyclomaticComplexity + "\n" +
                    "代码行数: " + linesOfCode + "\n" +
                    "注释行数: " + commentLines + "\n" +
                    "注释密度(%): " + String.format("%.2f", commentDensity) + "\n\n" +

                    "=== 用例图度量 ===\n" +
                    "用例点(UCP): " + useCasePoints + "\n" +
                    "参与者数: " + actors + "\n" +
                    "用例数: " + useCases;
        }
    }

    public static void main(String[] args) throws Exception {
        // 静态指定的Java文件路径
        String filePath = "D:\\grade3\\software_measure\\software-metrics\\src\\main\\java\\cn\\aicnn\\chatssespringboot\\service\\Impl\\AccountServiceImpl.java"; // 修改为你的实际文件路径

        File javaFile = new File(filePath);
        if (!javaFile.exists()) {
            System.out.println("文件不存在: " + javaFile.getAbsolutePath());
            return;
        }

        // 解析Java文件
        JavaParser javaParser = new JavaParser();
        FileInputStream in = new FileInputStream(javaFile);
        ParseResult<CompilationUnit> parseResult = javaParser.parse(in);

        if (parseResult.isSuccessful() && parseResult.getResult().isPresent()) {
            CompilationUnit cu = parseResult.getResult().get();
            MetricResults results = analyzeMetrics(cu, javaFile);
            System.out.println(results);
        } else {
            System.out.println("解析失败: " + parseResult.getProblems());
        }
    }

    private static MetricResults analyzeMetrics(CompilationUnit cu, File javaFile) {
        MetricResults results = new MetricResults();

        // 计算代码行数和注释行数
        calculateLineMetrics(cu, results, javaFile);

        // 计算功能点度量
        calculateFunctionPoints(cu, results);

        // 计算CK度量
        calculateCKMetrics(cu, results);

        // 计算LK度量
        calculateLKMetrics(cu, results);

        // 计算用例图度量
        calculateUseCaseMetrics(cu, results);

        return results;
    }

    private static void calculateLineMetrics(CompilationUnit cu, MetricResults results, File javaFile) {
        try {
            // 计算总行数
            results.linesOfCode = Files.readAllLines(javaFile.toPath()).size();

            // 计算注释行数
            results.commentLines = cu.getAllContainedComments().size();

            // 计算注释密度
            if (results.linesOfCode > 0) {
                results.commentDensity = (double) results.commentLines / results.linesOfCode * 100;
            }
        } catch (Exception e) {
            System.err.println("计算代码行数时出错: " + e.getMessage());
        }
    }

    private static void calculateFunctionPoints(CompilationUnit cu, MetricResults results) {
        // 外部输入(EI): 用户输入数据的方法调用
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodCallExpr n, Void arg) {
                super.visit(n, arg);
                String methodName = n.getNameAsString().toLowerCase();
                if (methodName.contains("input") || methodName.contains("read") ||
                        methodName.contains("scan") || methodName.contains("get")) {
                    results.externalInputs++;
                }
            }
        }.visit(cu, null);

        // 外部输出(EO): 向用户显示数据的方法调用
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodCallExpr n, Void arg) {
                super.visit(n, arg);
                String methodName = n.getNameAsString().toLowerCase();
                if (methodName.contains("print") || methodName.contains("write") ||
                        methodName.contains("show") || methodName.contains("display")) {
                    results.externalOutputs++;
                }
            }
        }.visit(cu, null);

        // 外部查询(EQ): 既包含输入又包含输出的方法
        results.externalQueries = (results.externalInputs + results.externalOutputs) / 2;

        // 内部逻辑文件(ILF): 类中的字段数量
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(FieldDeclaration n, Void arg) {
                super.visit(n, arg);
                results.internalLogicalFiles += n.getVariables().size();
            }
        }.visit(cu, null);

        // 外部接口文件(EIF): 引用的外部类数量
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                if (n.isInterface()) {
                    results.externalInterfaceFiles++;
                }
            }
        }.visit(cu, null);
    }

    private static void calculateCKMetrics(CompilationUnit cu, MetricResults results) {
        // WMC: 类中方法的数量
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                if (!n.isInterface()) {
                    results.wmc += n.getMethods().size();
                }
            }
        }.visit(cu, null);

        // DIT: 继承深度 (简化版，实际需要分析继承树)
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                if (n.getExtendedTypes().isNonEmpty()) {
                    results.dit = 1; // 简化处理，实际需要递归计算
                }
            }
        }.visit(cu, null);

        // NOC: 子类数量 (简化版，需要分析整个项目)
        results.noc = 0; // 需要完整项目分析

        // CBO: 类间耦合度 (统计引用的其他类数量)
        Set<String> referencedClasses = new HashSet<>();
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(com.github.javaparser.ast.type.ClassOrInterfaceType n, Void arg) {
                super.visit(n, arg);
                referencedClasses.add(n.getNameAsString());
            }
        }.visit(cu, null);
        results.cbo = referencedClasses.size();

        // RFC: 类的响应集合 (方法调用数)
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodDeclaration n, Void arg) {
                super.visit(n, arg);
                results.rfc++;
            }

            @Override
            public void visit(MethodCallExpr n, Void arg) {
                super.visit(n, arg);
                results.rfc++;
            }
        }.visit(cu, null);

        // LCOM: 方法内聚缺乏度 (计算不共享字段的方法比例)
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                if (!n.isInterface()) {
                    int methodPairs = 0;
                    int disjointPairs = 0;
                    List<MethodDeclaration> methods = n.getMethods();

                    for (int i = 0; i < methods.size(); i++) {
                        for (int j = i + 1; j < methods.size(); j++) {
                            methodPairs++;
                            if (!shareFields(methods.get(i), methods.get(j), n)) {
                                disjointPairs++;
                            }
                        }
                    }

                    if (methodPairs > 0) {
                        results.lcom = disjointPairs - methodPairs;
                    }
                }
            }
        }.visit(cu, null);
    }

    private static boolean shareFields(MethodDeclaration m1, MethodDeclaration m2,
                                       ClassOrInterfaceDeclaration clazz) {
        // 简化版，实际需要分析两个方法是否访问相同的字段
        return false;
    }

    private static void calculateLKMetrics(CompilationUnit cu, MetricResults results) {
        // 圈复杂度 (简化版，实际需要更复杂计算)
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodDeclaration n, Void arg) {
                super.visit(n, arg);
                // 基本复杂度计算: 每个决策点(if, for, while, case, catch)加1
                int complexity = 1; // 起始为1
                complexity += n.findAll(com.github.javaparser.ast.stmt.IfStmt.class).size();
                complexity += n.findAll(com.github.javaparser.ast.stmt.ForStmt.class).size();
                complexity += n.findAll(com.github.javaparser.ast.stmt.WhileStmt.class).size();
                complexity += n.findAll(com.github.javaparser.ast.stmt.SwitchStmt.class).size();
                complexity += n.findAll(com.github.javaparser.ast.stmt.CatchClause.class).size();

                results.cyclomaticComplexity += complexity;
            }
        }.visit(cu, null);
    }

    private static void calculateUseCaseMetrics(CompilationUnit cu, MetricResults results) {
        // 用例点(UCP)估算 (简化版)
        // 参与者数: 公共类或接口数
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                if (n.isPublic()) {
                    results.actors++;
                }
            }
        }.visit(cu, null);

        // 用例数: 公共方法数
        new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(MethodDeclaration n, Void arg) {
                super.visit(n, arg);
                if (n.isPublic()) {
                    results.useCases++;
                }
            }
        }.visit(cu, null);

        // 简化版用例点计算
        results.useCasePoints = results.actors * results.useCases;
    }
}